﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;

namespace Tsanie.OsuDevice.Components {
    public enum DownloadState {
        Downloading,
        Paused,
        Done,
        Error
    }
    [DefaultProperty("CurrentSize")]
    public class DownloadItem : Panel {
        public event EventHandler PauseClick { add { buttonPause.Click += value; } remove { buttonPause.Click -= value; } }
        public event EventHandler BrowserClick { add { buttonBrowser.Click += value; } remove { buttonBrowser.Click -= value; } }
        public event EventHandler ResumeClick { add { buttonResume.Click += value; } remove { buttonResume.Click -= value; } }

        #region - 属性 -
        [Description("获取或者设置文件图标")]
        [DefaultValue(null)]
        public Image FileIcon { get { return _fileIcon; } set { this._fileIcon = value; this.Invalidate(); } }
        private Image _fileIcon = null;

        [Description("获取或者设置文件名")]
        [DefaultValue("filename")]
        public string FileName { get { return _fileName; } set { this._fileName = value; this.Invalidate(); } }
        private string _fileName = "filename";

        [Description("获取或者设置总大小")]
        [DefaultValue(0)]
        public int TotalSize {
            get { return _totalSize; }
            set { this._totalSize = (value >= 0 ? value : 0); this.Invalidate(); }
        }
        private int _totalSize = 0;

        [Description("获取或者设置已下载大小")]
        [DefaultValue(0)]
        public int CurrentSize {
            get { return _currentSize < 0 ? 0 : (_currentSize > _totalSize && _totalSize > 0 ? _totalSize : _currentSize); }
            set {
                this._currentSize = value;
                this.Invalidate();
            }
        }
        private int _currentSize = 0;

        [Description("获取或者设置下载速度")]
        [DefaultValue(0)]
        public int Speed { get { return _speed; } set { this._speed = value; this.Invalidate(); } }
        private int _speed = 0;

        [Description("获取或者设置下载状态")]
        [DefaultValue(DownloadState.Downloading)]
        public DownloadState DownloadState {
            get { return _downloadState; }
            set {
                _downloadState = value;
                this.Invoke(new MethodInvoker(delegate {
                    this.buttonResume.Visible = false;
                    this.buttonPause.Visible = false;
                    this.buttonBrowser.Visible = false;
                    if (value == Components.DownloadState.Downloading) {
                        this.buttonPause.Visible = true;
                    } else if (value == Components.DownloadState.Paused) {
                        this.buttonResume.Visible = true;
                    } else if (value == Components.DownloadState.Done) {
                        this.buttonBrowser.Visible = true;
                    }
                    this.Invalidate();
                }));
            }
        }
        private DownloadState _downloadState = DownloadState.Downloading;

        [Description("获取或者设置关联的下载器")]
        internal Tsanie.OsuDevice.Network.Downloader Downloader { get; set; }

        [DefaultValue(typeof(Size), "0, 46")]
        public override Size MaximumSize { get { return base.MaximumSize; } set { base.MaximumSize = value; } }
        [DefaultValue(typeof(Size), "0, 46")]
        public override Size MinimumSize { get { return base.MinimumSize; } set { base.MinimumSize = value; } }
        [DefaultValue(DockStyle.Top)]
        public override DockStyle Dock { get { return base.Dock; } set { } }
        public override Font Font {
            get { return base.Font; }
            set {
                base.Font = value;
                this._fontBold = new Font(base.Font, FontStyle.Bold);
            }
        }
        private Font _fontBold;
        #endregion

        public ListViewItem OwnerItem { get; private set; }

        private Button buttonPause;
        private Button buttonBrowser;
        private Button buttonResume;
        private Rectangle rectTexture = new Rectangle(0, 0, 48, 24);
        private bool gotFocus = false;
        private static Color ColorBack = Color.FromArgb(240, 240, 240);

        public DownloadItem(ListViewItem item)
            : base() {
            this.OwnerItem = item;

            _fontBold = new Font(this.Font, FontStyle.Bold);
            base.MinimumSize = new Size(0, 46);
            base.MaximumSize = this.MinimumSize;
            base.Dock = DockStyle.Top;
            this.buttonBrowser = new Button();
            this.buttonBrowser.Text = "";
            this.buttonBrowser.Image = Tsanie.OsuDevice.Properties.Resources.browser;
            this.buttonBrowser.Size = new Size(28, 28);
            this.buttonBrowser.Location = new Point(this.ClientSize.Width - 44, 9);
            this.buttonBrowser.BackColor = Color.Transparent;
            this.buttonBrowser.Visible = false;
            this.buttonBrowser.GotFocus += new EventHandler(OnGotFocus);
            this.buttonBrowser.LostFocus += new EventHandler(OnLostFocus);
            this.buttonPause = new Button();
            this.buttonPause.Text = "";
            this.buttonPause.Image = Tsanie.OsuDevice.Properties.Resources.pause;
            this.buttonPause.Size = new Size(28, 28);
            this.buttonPause.Location = new Point(this.ClientSize.Width - 44, 9);
            this.buttonPause.BackColor = Color.Transparent;
            this.buttonPause.Visible = true;
            this.buttonPause.GotFocus += new EventHandler(OnGotFocus);
            this.buttonPause.LostFocus += new EventHandler(OnLostFocus);
            this.buttonResume = new Button();
            this.buttonResume.Text = "";
            this.buttonResume.Image = Tsanie.OsuDevice.Properties.Resources.resume;
            this.buttonResume.Size = new Size(28, 28);
            this.buttonResume.Location = new Point(this.ClientSize.Width - 44, 9);
            this.buttonResume.BackColor = Color.Transparent;
            this.buttonResume.Visible = false;
            this.buttonResume.GotFocus += new EventHandler(OnGotFocus);
            this.buttonResume.LostFocus += new EventHandler(OnLostFocus);
            this.Controls.Add(this.buttonPause);
            this.Controls.Add(this.buttonBrowser);
            this.Controls.Add(this.buttonResume);

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        }

        public void SetFocus() {
            if (buttonPause.Visible)
                buttonPause.Focus();
            else if (buttonBrowser.Visible)
                buttonBrowser.Focus();
            else if (buttonResume.Visible)
                buttonResume.Focus();
        }

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            if (gotFocus)
                g.Clear(DownloadItem.ColorBack);
            //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
            Image image = (this._downloadState == Components.DownloadState.Paused ?
                Tsanie.OsuDevice.Properties.Resources.paused :
                Tsanie.OsuDevice.Properties.Resources.normal);
            if (_totalSize > 0) {
                g.DrawImage(image, 0, 0, this.ClientSize.Width * (long)this.CurrentSize / this._totalSize, this.ClientSize.Height);
            }
            if (_fileIcon != null)
                g.DrawImage(_fileIcon, 4, 4, 32, 32);
            g.DrawString(GetString(_fileName, this.ClientSize.Width - 170, this.Font, g),
                this.Font, Brushes.Black, 40, 8);
            g.DrawString(GetString(GetSize(this.CurrentSize) + "/" + GetSize(_totalSize) + " (剩余时间: " + (_totalSize > 0 && this.Speed > 0 ? GetTime((_totalSize - this.CurrentSize) / this.Speed) : "未知") + ")", this.ClientSize.Width - 170, this.Font, g),
                this.Font, Brushes.Gray, 40, 26);
            if (_downloadState == Components.DownloadState.Downloading) {
                g.DrawString(GetSize(_speed) + "/s", _fontBold, Brushes.Black, this.ClientSize.Width - 130, 18);
            }

            g.DrawLine(Pens.LightGray, 0, this.ClientSize.Height, this.ClientSize.Width, this.ClientSize.Height);
        }
        protected override void OnResize(EventArgs eventargs) {
            base.OnResize(eventargs);
            if (this.buttonBrowser != null && this.buttonPause != null && this.buttonResume != null) {
                this.buttonBrowser.Location = new Point(this.ClientSize.Width - 40, 9);
                this.buttonPause.Location = new Point(this.ClientSize.Width - 40, 9);
                this.buttonResume.Location = new Point(this.ClientSize.Width - 40, 9);
            }
        }

        private void OnGotFocus(object sender, EventArgs e) {
            gotFocus = true;
            this.Invalidate();
        }
        private void OnLostFocus(object sender, EventArgs e) {
            gotFocus = false;
            this.Invalidate();
        }

        private string GetSize(int size) {
            if (size <= 0)
                return "未知";
            if (size > 1048576) {
                return (size / 1048576f).ToString("0.00") + " MB";
            } else if (size > 1024) {
                return (size / 1024f).ToString("0.00") + " KB";
            }
            return size + " B";
        }
        private string GetTime(int seconds) {
            string rtn = "";
            if (seconds > 3600) {
                int h = seconds / 3600;
                rtn = h + "小时";
                seconds -= h * 3600;
            }
            if (seconds > 60) {
                int m = seconds / 60;
                rtn += m + "分钟";
                seconds -= m * 60;
            }
            rtn += seconds + "秒";
            return rtn;
        }
        private string GetString(string str, int width, Font font, Graphics g) {
            if (str.Length < 1)
                return str;
            if (g.MeasureString(str, font).Width > width) {
                string rtn = str.Substring(0, str.Length - 1);
                while (g.MeasureString(rtn, font).Width + 20 > width) {
                    if (rtn.Length < 1)
                        return rtn + "...";
                    rtn = rtn.Substring(0, rtn.Length - 1);
                }
                return rtn + "...";
            }
            return str;
        }
    }
}
